<template>
  <div class="model-training-container">
    <!-- 页面标题 -->
    <div class="page-header">
      <h2>模型训练</h2>
      <p class="subtitle">ML.NET机器学习模型训练与优化</p>
    </div>

    <!-- 模型配置 -->
    <el-card class="model-config" shadow="hover">
      <template #header>
        <div class="card-header">
          <span>模型配置</span>
          <el-button type="primary" @click="startTraining" :loading="training" :disabled="!canStartTraining">
            开始训练
          </el-button>
        </div>
      </template>

      <el-form :model="modelConfig" label-width="120px">
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item label="算法类型">
              <el-select v-model="modelConfig.algorithmType" placeholder="选择算法">
                <el-option label="线性回归" value="linear" />
                <el-option label="随机森林" value="randomforest" />
                <el-option label="梯度提升" value="gradientboosting" />
                <el-option label="神经网络" value="neural" />
                <el-option label="支持向量机" value="svm" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="训练集比例">
              <el-slider
                v-model="modelConfig.trainRatio"
                :min="50"
                :max="90"
                :step="5"
                show-input
                input-size="small"
              />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="交叉验证折数">
              <el-input-number
                v-model="modelConfig.crossValidationFolds"
                :min="3"
                :max="10"
                :step="1"
              />
            </el-form-item>
          </el-col>
        </el-row>

        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item label="最大迭代次数">
              <el-input-number
                v-model="modelConfig.maxIterations"
                :min="100"
                :max="10000"
                :step="100"
              />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="学习率">
              <el-input-number
                v-model="modelConfig.learningRate"
                :min="0.001"
                :max="1"
                :step="0.001"
                :precision="3"
              />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="正则化强度">
              <el-input-number
                v-model="modelConfig.regularization"
                :min="0"
                :max="1"
                :step="0.01"
                :precision="2"
              />
            </el-form-item>
          </el-col>
        </el-row>

        <el-form-item label="超参数优化">
          <el-checkbox-group v-model="modelConfig.hyperparameterOptimization">
            <el-checkbox label="自动调参" value="auto" />
            <el-checkbox label="网格搜索" value="grid" />
            <el-checkbox label="贝叶斯优化" value="bayesian" />
          </el-checkbox-group>
        </el-form-item>
      </el-form>
    </el-card>

    <!-- 训练进度 -->
    <el-card class="training-progress" shadow="hover" v-if="isTraining">
      <template #header>
        <div class="card-header">
          <span>训练进度</span>
          <el-button type="danger" @click="stopTraining" :loading="stopping">
            停止训练
          </el-button>
        </div>
      </template>

      <div class="progress-section">
        <el-progress
          :percentage="trainingProgress.overall"
          :status="trainingProgress.status"
          :stroke-width="20"
        />
        <div class="progress-details">
          <p>当前阶段: {{ trainingProgress.currentStage }}</p>
          <p>已训练轮次: {{ trainingProgress.currentEpoch }} / {{ trainingProgress.totalEpochs }}</p>
          <p>当前损失: {{ trainingProgress.currentLoss.toFixed(4) }}</p>
          <p>训练时间: {{ formatTime(trainingProgress.elapsedTime) }}</p>
        </div>
      </div>

      <!-- 实时训练曲线 -->
      <div class="training-charts">
        <el-row :gutter="20">
          <el-col :span="12">
            <div class="chart-container">
              <h4>损失函数变化</h4>
              <v-chart class="chart" :option="lossChartOption" :autoresize="true" />
            </div>
          </el-col>
          <el-col :span="12">
            <div class="chart-container">
              <h4>准确率变化</h4>
              <v-chart class="chart" :option="accuracyChartOption" :autoresize="true" />
            </div>
          </el-col>
        </el-row>
      </div>
    </el-card>

    <!-- 模型评估 -->
    <el-card class="model-evaluation" shadow="hover" v-if="evaluationResults">
      <template #header>
        <div class="card-header">
          <span>模型评估</span>
          <div class="header-actions">
            <el-button type="success" @click="saveModel">保存模型</el-button>
            <el-button @click="exportEvaluation">导出评估报告</el-button>
          </div>
        </div>
      </template>

      <!-- 评估指标 -->
      <div class="evaluation-metrics">
        <el-row :gutter="20">
          <el-col :span="6">
            <div class="metric-card">
              <div class="metric-number">{{ evaluationResults.accuracy.toFixed(2) }}%</div>
              <div class="metric-label">准确率</div>
            </div>
          </el-col>
          <el-col :span="6">
            <div class="metric-card">
              <div class="metric-number">{{ evaluationResults.precision.toFixed(2) }}%</div>
              <div class="metric-label">精确率</div>
            </div>
          </el-col>
          <el-col :span="6">
            <div class="metric-card">
              <div class="metric-number">{{ evaluationResults.recall.toFixed(2) }}%</div>
              <div class="metric-label">召回率</div>
            </div>
          </el-col>
          <el-col :span="6">
            <div class="metric-card">
              <div class="metric-number">{{ evaluationResults.f1Score.toFixed(2) }}%</div>
              <div class="metric-label">F1分数</div>
            </div>
          </el-col>
        </el-row>
      </div>

      <!-- 混淆矩阵 -->
      <div class="confusion-matrix">
        <h4>混淆矩阵</h4>
        <el-table :data="evaluationResults.confusionMatrix" border style="width: 300px; margin: 0 auto;">
          <el-table-column prop="actual" label="实际值" width="100" />
          <el-table-column prop="predicted" label="预测值" width="100" />
          <el-table-column prop="count" label="数量" width="100" />
        </el-table>
      </div>

      <!-- 特征重要性 -->
      <div class="feature-importance">
        <h4>特征重要性</h4>
        <el-table :data="evaluationResults.featureImportance" border style="width: 100%">
          <el-table-column prop="feature" label="特征名称" width="200" />
          <el-table-column prop="importance" label="重要性" width="150">
            <template #default="scope">
              <el-progress 
                :percentage="scope.row.importance" 
                :color="getImportanceColor(scope.row.importance)"
              />
            </template>
          </el-table-column>
          <el-table-column prop="description" label="描述" />
        </el-table>
      </div>
    </el-card>

    <!-- 模型历史 -->
    <el-card class="model-history" shadow="hover">
      <template #header>
        <div class="card-header">
          <span>模型历史</span>
          <el-button @click="loadModelHistory">刷新</el-button>
        </div>
      </template>

      <el-table :data="modelHistory" border style="width: 100%">
        <el-table-column prop="modelName" label="模型名称" width="150" />
        <el-table-column prop="algorithm" label="算法" width="120" />
        <el-table-column prop="accuracy" label="准确率" width="100">
          <template #default="scope">
            {{ scope.row.accuracy.toFixed(2) }}%
          </template>
        </el-table-column>
        <el-table-column prop="trainingDate" label="训练日期" width="150" />
        <el-table-column prop="status" label="状态" width="100">
          <template #default="scope">
            <el-tag :type="getModelStatusType(scope.row.status)">
              {{ scope.row.status }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="200">
          <template #default="scope">
            <el-button type="primary" size="small" @click="loadModel(scope.row)">
              加载
            </el-button>
            <el-button type="success" size="small" @click="deployModel(scope.row)">
              部署
            </el-button>
            <el-button type="danger" size="small" @click="deleteModel(scope.row)">
              删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-card>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { LineChart } from 'echarts/charts'
import http from '@/http/axiosHelper'
import {
  TitleComponent,
  TooltipComponent,
  LegendComponent,
  GridComponent
} from 'echarts/components'
import VChart from 'vue-echarts'
import axios from 'axios'

// 注册 ECharts 组件
use([
  CanvasRenderer,
  LineChart,
  TitleComponent,
  TooltipComponent,
  LegendComponent,
  GridComponent
])

// 模型配置
const modelConfig = reactive({
  algorithmType: 'randomforest',
  trainRatio: 80,
  crossValidationFolds: 5,
  maxIterations: 1000,
  learningRate: 0.1,
  regularization: 0.01,
  hyperparameterOptimization: ['auto']
})

// 训练状态
const training = ref(false)
const stopping = ref(false)
const isTraining = ref(false)

// 训练进度
const trainingProgress = reactive({
  overall: 0,
  status: '',
  currentStage: '',
  currentEpoch: 0,
  totalEpochs: 0,
  currentLoss: 0,
  elapsedTime: 0
})

// 评估结果
interface EvaluationResults {
  accuracy: number
  precision: number
  recall: number
  f1Score: number
  confusionMatrix: number[][]
  featureImportance: { feature: string; importance: number }[]
}

const evaluationResults = ref<EvaluationResults | null>(null)

// 模型历史
interface ModelHistory {
  id: string
  name: string
  algorithm: string
  accuracy: number
  createdTime: string
  status: string
}

const modelHistory = ref<ModelHistory[]>([])

// 图表数据
const lossData = ref([])
const accuracyData = ref([])

// 计算是否可以开始训练
const canStartTraining = computed(() => {
  return modelConfig.algorithmType && modelConfig.trainRatio > 0
})

// 损失函数图表配置
const lossChartOption = computed(() => ({
  title: {
    text: '训练损失',
    left: 'center'
  },
  tooltip: {
    trigger: 'axis'
  },
  xAxis: {
    type: 'category',
    data: lossData.value.map((_, index) => index + 1)
  },
  yAxis: {
    type: 'value'
  },
  series: [
    {
      name: '训练损失',
      type: 'line',
      data: lossData.value,
      smooth: true
    }
  ]
}))

// 准确率图表配置
const accuracyChartOption = computed(() => ({
  title: {
    text: '训练准确率',
    left: 'center'
  },
  tooltip: {
    trigger: 'axis'
  },
  xAxis: {
    type: 'category',
    data: accuracyData.value.map((_, index) => index + 1)
  },
  yAxis: {
    type: 'value',
    min: 0,
    max: 100
  },
  series: [
    {
      name: '训练准确率',
      type: 'line',
      data: accuracyData.value,
      smooth: true
    }
  ]
}))

// 开始训练
const startTraining = async () => {
  training.value = true
  isTraining.value = true
  
  try {
    const response = await axios.post('/api/MLNet/StartTraining', {
      config: modelConfig
    })
    
    if (response.data.code === 200) {
      ElMessage.success('训练已开始')
      startProgressMonitoring()
    } else {
      ElMessage.error(response.data.message || '训练启动失败')
    }
  } catch (error) {
    console.error('训练启动失败:', error)
    ElMessage.error('训练启动时发生错误')
  } finally {
    training.value = false
  }
}

// 停止训练
const stopTraining = async () => {
  stopping.value = true
  try {
    const response = await axios.post('/api/MLNet/StopTraining')
    if (response.data.code === 200) {
      ElMessage.success('训练已停止')
      isTraining.value = false
    }
  } catch (error) {
    console.error('停止训练失败:', error)
    ElMessage.error('停止训练时发生错误')
  } finally {
    stopping.value = false
  }
}

// 监控训练进度
const startProgressMonitoring = () => {
  const interval = setInterval(async () => {
    try {
      const response = await axios.get('/api/MLNet/GetTrainingProgress')
      if (response.data.code === 200) {
        const progress = response.data.data
        Object.assign(trainingProgress, progress)
        
        // 更新图表数据
        if (progress.lossHistory) {
          lossData.value = progress.lossHistory
        }
        if (progress.accuracyHistory) {
          accuracyData.value = progress.accuracyHistory
        }
        
        // 检查训练是否完成
        if (progress.status === 'completed') {
          clearInterval(interval)
          isTraining.value = false
          await loadEvaluationResults()
          ElMessage.success('训练完成！')
        }
      }
    } catch (error) {
      console.error('获取训练进度失败:', error)
    }
  }, 1000)
}

// 加载评估结果
const loadEvaluationResults = async () => {
  try {
    const response = await axios.get('/api/MLNet/GetEvaluationResults')
    if (response.data.code === 200) {
      evaluationResults.value = response.data.data
    }
  } catch (error) {
    console.error('加载评估结果失败:', error)
  }
}

// 保存模型
const saveModel = async () => {
  try {
    const response = await axios.post('/api/MLNet/SaveModel', {
      modelName: `outbound_prediction_${new Date().toISOString().slice(0, 19).replace(/:/g, '-')}`,
      evaluationResults: evaluationResults.value
    })
    
    if (response.data.code === 200) {
      ElMessage.success('模型保存成功')
      loadModelHistory()
    } else {
      ElMessage.error(response.data.message || '模型保存失败')
    }
  } catch (error) {
    console.error('保存模型失败:', error)
    ElMessage.error('保存模型时发生错误')
  }
}

// 加载模型历史
const loadModelHistory = async () => {
  try {
    const response = await axios.get('/api/MLNet/GetModelHistory')
    if (response.data.code === 200) {
      modelHistory.value = response.data.data
    }
  } catch (error) {
    console.error('加载模型历史失败:', error)
  }
}

// 加载模型
const loadModel = async (model: any) => {
  try {
    const response = await axios.post('/api/MLNet/LoadModel', {
      modelId: model.id
    })
    
    if (response.data.code === 200) {
      ElMessage.success('模型加载成功')
      evaluationResults.value = response.data.data.evaluationResults
    } else {
      ElMessage.error(response.data.message || '模型加载失败')
    }
  } catch (error) {
    console.error('加载模型失败:', error)
    ElMessage.error('加载模型时发生错误')
  }
}

// 部署模型
const deployModel = async (model: any) => {
  try {
    const response = await axios.post('/api/MLNet/DeployModel', {
      modelId: model.id
    })
    
    if (response.data.code === 200) {
      ElMessage.success('模型部署成功')
    } else {
      ElMessage.error(response.data.message || '模型部署失败')
    }
  } catch (error) {
    console.error('部署模型失败:', error)
    ElMessage.error('部署模型时发生错误')
  }
}

// 删除模型
const deleteModel = async (model: any) => {
  try {
    await ElMessageBox.confirm(
      `确定要删除模型 "${model.modelName}" 吗？`,
      '确认删除',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }
    )
    
    const response = await axios.delete(`/api/MLNet/DeleteModel/${model.id}`)
    
    if (response.data.code === 200) {
      ElMessage.success('模型删除成功')
      loadModelHistory()
    } else {
      ElMessage.error(response.data.message || '模型删除失败')
    }
  } catch (error) {
    if (error !== 'cancel') {
      console.error('删除模型失败:', error)
      ElMessage.error('删除模型时发生错误')
    }
  }
}

// 导出评估报告
const exportEvaluation = () => {
  ElMessage.success('评估报告导出功能开发中...')
}

// 格式化时间
const formatTime = (seconds: number) => {
  const hours = Math.floor(seconds / 3600)
  const minutes = Math.floor((seconds % 3600) / 60)
  const secs = seconds % 60
  return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`
}

// 获取重要性颜色
const getImportanceColor = (importance: number) => {
  if (importance >= 80) return '#67C23A'
  if (importance >= 60) return '#E6A23C'
  if (importance >= 40) return '#F56C6C'
  return '#909399'
}

// 获取模型状态类型
const getModelStatusType = (status: string) => {
  switch (status) {
    case 'active': return 'success'
    case 'inactive': return 'info'
    case 'training': return 'warning'
    case 'error': return 'danger'
    default: return 'info'
  }
}

onMounted(() => {
  loadModelHistory()
})
</script>

<style scoped>
.model-training-container {
  padding: 20px;
  background-color: #f5f7fa;
  min-height: 100vh;
}

.page-header {
  text-align: center;
  margin-bottom: 30px;
}

.page-header h2 {
  color: #303133;
  margin-bottom: 10px;
}

.subtitle {
  color: #909399;
  font-size: 14px;
}

.model-config,
.training-progress,
.model-evaluation,
.model-history {
  margin-bottom: 20px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.header-actions {
  display: flex;
  gap: 10px;
}

.progress-section {
  margin-bottom: 30px;
}

.progress-details {
  margin-top: 15px;
  text-align: center;
}

.progress-details p {
  margin: 5px 0;
  color: #606266;
}

.training-charts {
  margin-top: 30px;
}

.chart-container {
  background: white;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
}

.chart-container h4 {
  margin-bottom: 20px;
  color: #303133;
}

.chart {
  height: 300px;
}

.evaluation-metrics {
  margin-bottom: 30px;
}

.metric-card {
  text-align: center;
  padding: 20px;
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
}

.metric-number {
  font-size: 24px;
  font-weight: bold;
  color: #409EFF;
  margin-bottom: 10px;
}

.metric-label {
  color: #909399;
  font-size: 14px;
}

.confusion-matrix,
.feature-importance {
  margin-bottom: 30px;
}

.confusion-matrix h4,
.feature-importance h4 {
  margin-bottom: 20px;
  color: #303133;
}
</style> 